package gruppenkalenderProjekt.db;

import gruppenkalenderProjekt.data.BenutzerImpl;
import java.rmi.RemoteException;
import java.sql.*;
import java.util.Vector;

import gruppenkalenderProjekt.data.Benutzer;

// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.9C35D869-5F17-09CB-EFF1-96AB7727E0DC]
// </editor-fold>
/** Agiert als Schnittstelle zur Benutzer Tabelle der Datenbank.
 * Beinhaltet die SQL Statements zur Auslesung und Datenmanipulation.
 *
 * @author  Rathke,Thies
 * @coauthor Gruppe 2
 */
public class BenutzerMapper {

    private static BenutzerMapper benutzerMapper = null;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.37B6DDB0-3B5E-64AB-6401-5395D0CFF79D]
    // </editor-fold> 

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.04765412-9DFE-2D23-D31A-D4E7DA3E8E63]
    // </editor-fold> 
    protected BenutzerMapper() {
    }

    /**Methode die die Umsetzung des Singleton-Patterns ermoeglicht
     *
     * @return
     */
    public static BenutzerMapper benutzerMapper() {
        // Wenn noch kein Benutzer-Mapper existiert wird dieser jetzt erstellt
        if (benutzerMapper == null) {
            benutzerMapper = new BenutzerMapper();
        }
        System.out.print("BenutzerMapper erstellt...");
        return benutzerMapper;
    }

    /**Methode die Alle Benutzer als Vector zurueck gibt
     *
     * @return result Ein Vector mit allen BenutzerObjekten
     */
    public Vector<Benutzer> findeAlleBenutzer() {
        //Ein Connection Objekt wird erstellt und Datenbankverbindung wird mitgegeben
        Connection con = DBConnection.connection();
        //Ein Vektor vom Typ Kategorie wird erstellt
        Vector<Benutzer> result = new Vector<Benutzer>();

        try {
            //leeres Statement erstellen
            Statement stmt = con.createStatement();
            //Neues ResultSet erstellen und Datenbankinhalt in dieser ablegen
            ResultSet rs = stmt.executeQuery(
                    "SELECT * FROM benutzer ");
            // Solange weitere Datensätze im Result Set vorhanden
            while (rs.next()) {
                try {
                    //Lokales Objekt zum Zwischenspeichern erstellen
                    Benutzer b = new BenutzerImpl();
                    b.setBenutzerID(rs.getInt("b_ID"));
                    b.setBenutzername(rs.getString("benutzername"));
                    b.setVorname(rs.getString("vorname"));
                    b.setNachname(rs.getString("nachname"));
                    b.setEmail(rs.getString("email"));
                    b.setTelefon(rs.getString("telefon"));
                    b.setRaum(rs.getString("raum"));

                    //Mapping von tinyint (mySQL) auf Boolean (java)
                    if (rs.getInt("superbenutzer") == 0) { //wenn tinyint = 0 ist der boolean false
                        b.setSuperbenutzer(false);
                    } else {
                        b.setSuperbenutzer(true);//wenn tinyint = 1 ist der boolean true
                    }

                    //Objekte dem Vektor hinzufügen
                    result.addElement(b);

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }

        return result;
    }

    /**Methode die einen Benutzer zuerueck gibt
     *
     * @param b_ID Die ID des gewuenschten Benutzers
     * @return b Ein BenutzerObjekt
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.F6992B8C-9086-A0B1-B3D2-70A33C624EA5]
    // </editor-fold> 
    public Benutzer findeBenutzerMitID(int b_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT * FROM benutzer " +
                    "WHERE b_ID=" + b_ID);

            if (rs.next()) {
                try {
                    Benutzer b = new BenutzerImpl();
                    b.setBenutzerID(rs.getInt("b_ID"));
                    b.setBenutzername(rs.getString("benutzername"));
                    b.setVorname(rs.getString("vorname"));
                    b.setNachname(rs.getString("nachname"));
                    b.setEmail(rs.getString("email"));
                    b.setTelefon(rs.getString("telefon"));
                    b.setRaum(rs.getString("raum"));

                    //Mapping von tinyint (mySQL) auf Boolean (java)
                    if (rs.getInt("superbenutzer") == 0) { //wenn tinyint = 0 ist der boolean false
                        b.setSuperbenutzer(false);
                    } else {
                        b.setSuperbenutzer(true);//wenn tinyint = 1 ist der boolean true
                    }

                    return b;


                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;

    }

    /**Methode die einen Benutzer in die Datenbank schreibt
     *
     * @param benutzer Der zu speichernde Benutzer
     * @return b Ein BenutzerObjekt
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.FAC21EB3-6F44-B8E3-8AAE-D68E1F320157]
    // </editor-fold> 
    public Benutzer insert(Benutzer benutzer) {

        Connection con = DBConnection.connection();         //connection holen

        try {
            Statement stmt = con.createStatement();             //neues statement anlegen

            //folgendes Mapping muss vor dem INSERT Statement gemacht werden, da wir sonst mit einem
            //StringBuffer arbeiten muessten, der den Code unuebersichtlicher macht
            int superbenutzer; //lokale Variable anlegen um 0 oder 1 zu speichern
            if (benutzer.isSuperbenutzer() == false) { //abfrage ob der Benutzer Superbenutzer ist
                superbenutzer = 0; //bei tinyint in mysql: 0 = false
            } else {
                superbenutzer = 1; //bei tinyint in mysql: 1 = true
            }

            stmt.executeUpdate("INSERT INTO benutzer (benutzername, vorname, nachname, email, telefon, raum, superbenutzer) " + //einfügen des neuen objekts in db
                    "VALUES ('" +
                    benutzer.getBenutzername() + "','" +
                    benutzer.getVorname() + "','" +
                    benutzer.getNachname() + "','" +
                    benutzer.getEmail() + "','" +
                    benutzer.getTelefon() + "','" +
                    benutzer.getRaum() + "','" +
                    superbenutzer + "')"); //hier wird der oben gemappte wert (0 oder 1) dem Insert Statement hinzugefuegt


            try {
                stmt = con.createStatement();

                ResultSet rs = stmt.executeQuery("SELECT b_ID FROM benutzer WHERE benutzer.benutzername = '" + benutzer.getBenutzername() + "' AND benutzer.vorname = '" + benutzer.getVorname() + "' AND benutzer.nachname = '" + benutzer.getNachname() + "' AND benutzer.email = '" + benutzer.getEmail() + "' AND benutzer.telefon = '" + benutzer.getTelefon() + "' AND benutzer.raum = '" + benutzer.getRaum() + "' AND benutzer.superbenutzer = '" + superbenutzer + "'");

                if (rs.next()) {
                    benutzer.setBenutzerID(rs.getInt("b_ID"));
                }
            } catch (SQLException e3) {
                e3.printStackTrace();
            }
        } catch (RemoteException ex) {
            ex.printStackTrace();
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return benutzer; //eingefügtes Objekt wird wieder zurückgegeben
    }

    /**Methode die einen Benutzer aus der Datenbank loescht
     *
     * @param benutzer der zu loeschende Benutzer
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.A45BFEEC-6810-5D75-1111-0997D8696DDE]
    // </editor-fold> 
    public void delete(Benutzer benutzer) {
        Connection con = DBConnection.connection();

        int k_id = 0;
        int e_id = 0;
        try {
            Statement stmt = con.createStatement();

            //benutzer loeschen
            stmt.executeUpdate("DELETE FROM benutzer " +
                    "WHERE b_ID=" + benutzer.getBenutzerID());

            //alle teilnehmer loeschen
            stmt = con.createStatement();
            stmt.executeUpdate("DELETE FROM zugehoerigkeit " +
                    "WHERE b_ID=" + benutzer.getBenutzerID());




            stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT k_ID FROM besitz " +
                    "WHERE b_ID='" + benutzer.getBenutzerID() + "'");


            while (rs.next()) {
                k_id = rs.getInt("k_ID");

                //besitzer loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM besitz " +
                        "WHERE k_ID=" + k_id);

                //kalender loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM kalender " +
                        "WHERE k_ID=" + k_id);

                //alle teilnehmer loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM zugehoerigkeit " +
                        "WHERE k_ID=" + k_id);
            }


            //alle teilnehmer loeschen
            stmt = con.createStatement();
            stmt.executeUpdate("DELETE FROM sichtbarkeit " +
                    "WHERE b_ID=" + benutzer.getBenutzerID());


            stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT e_ID FROM erstellung " +
                    "WHERE b_ID='" + benutzer.getBenutzerID() + "'");

            while (rs.next()) {
                e_id = rs.getInt("e_ID");

                //besitzer loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM erstellung " +
                        "WHERE e_ID=" + e_id);

                //kalendereintrag loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM kalendereintrag " +
                        "WHERE e_ID=" + e_id);

                //alle teilnehmer loeschen
                stmt = con.createStatement();
                stmt.executeUpdate("DELETE FROM sichtbarkeit " +
                        "WHERE e_ID=" + e_id);
            }
            
        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**Methode die einen Datensatz in der Datenbank aktualisiert
     *
     * @param benutzer Der zu aktualisiernde Benutzer
     * @return b Ein BenutzerObjekt
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.8F6A90B7-C8DD-359C-5E38-07B4C39E2BBE]
    // </editor-fold> 
    public Benutzer update(Benutzer benutzer) {
        Connection con = DBConnection.connection();
        try {
            Statement stmt = con.createStatement();

            //folgendes Mapping muss vor dem UPDATE Statement gemacht werden, da wir sonst mit einem
            //StringBuffer arbeiten muessten, der den Code unuebersichtlicher macht
            int superbenutzer; //lokale Variable anlegen um 0 oder 1 zu speichern
            if (benutzer.isSuperbenutzer() == false) { //abfrage ob der Benutzer Superbenutzer ist
                superbenutzer = 0; //bei tinyint in mysql: 0 = false
            } else {
                superbenutzer = 1; //bei tinyint in mysql: 1 = true
            }


            stmt.executeUpdate("UPDATE benutzer " +
                    "SET " +
                    "benutzername='" + benutzer.getBenutzername() +
                    "',vorname='" + benutzer.getVorname() +
                    "',nachname='" + benutzer.getNachname() +
                    "',email='" + benutzer.getEmail() +
                    "',telefon='" + benutzer.getTelefon() +
                    "',raum='" + benutzer.getRaum() +
                    "',superbenutzer='" + superbenutzer +
                    "' WHERE b_ID=" + benutzer.getBenutzerID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return benutzer; //geändertes Objekt wird wieder zurückgegeben

    }

    /**Methode die den Besitzer eines Kalenders findet
     *
     * @param k_ID die ID des Kalenders
     * @return b Ein BenutzerObjekt
     */
    public Benutzer findeBesitzerVonKalender(int k_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT b_ID FROM besitz " +
                    "WHERE k_ID='" + k_ID + "'");

            if (rs.next()) {
                return this.findeBenutzerMitID(rs.getInt("b_ID"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;

    }

    /**Methode die alle Benutzer eines Kalenders findet
     *
     * @param k_ID Die ID des Kalenders
     * @return result Ein Vector mit allen Benutzern
     */
    public Vector<Benutzer> findeBenutzerVonKalender(int k_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung

        Vector<Benutzer> result = new Vector<Benutzer>(); //Ergebnisvektor

        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT b_ID FROM zugehoerigkeit " +
                    "WHERE k_ID='" + k_ID + "'");

            while (rs.next()) {
                result.addElement(this.findeBenutzerMitID(rs.getInt("b_ID")));
            }
            return result;

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**Methode findet den Ersteller eines Kalendereintrags und gibt ihn zurueck
     *
     * @param e_ID ID eines Kalendereintrags
     * @return b Ein Benutzerobjekt
     */
    public Benutzer findeErstellerVonKalendereintrag(int e_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT b_ID FROM erstellung " +
                    "WHERE e_ID='" + e_ID + "'");

            if (rs.next()) {
                return this.findeBenutzerMitID(rs.getInt("b_ID"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;

    }

    /**Methode die alle teilnehmer eines Kalendereintrags findet und als Vector
     * zurueck gibt
     * @param e_ID ID des Kalendereintrags
     * @return result Ein Vector mit allen Teilnehmern
     */
    public Vector<Benutzer> findeTeilnehmerVonKalendereintrag(int e_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung

        Vector<Benutzer> result = new Vector<Benutzer>(); //Ergebnisvektor

        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT b_ID FROM sichtbarkeit " +
                    "WHERE e_ID='" + e_ID + "'");

            while (rs.next()) {
                result.addElement(this.findeBenutzerMitID(rs.getInt("b_ID")));
            }
            return result;

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**Methode die einen Benutzer nach seinem Benutzername findet
     *
     * @param benutzername Der Benutzername der zum Log-In verwendet wird
     * @return b Ein Benutzerobjekt
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,id=DCE.F6992B8C-9086-A0B1-B3D2-70A33C624EA5]
    // </editor-fold>
    public Benutzer findeBenutzerMitBenutzername(String benutzername) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT * FROM benutzer " +
                    "WHERE benutzername='" + benutzername + "'");

            if (rs.next()) {
                try {
                    Benutzer b = new BenutzerImpl();
                    b.setBenutzerID(rs.getInt("b_ID"));
                    b.setBenutzername(rs.getString("benutzername"));
                    b.setVorname(rs.getString("vorname"));
                    b.setNachname(rs.getString("nachname"));
                    b.setEmail(rs.getString("email"));
                    b.setTelefon(rs.getString("telefon"));
                    b.setRaum(rs.getString("raum"));

                    //Mapping von tinyint (mySQL) auf Boolean (java)
                    if (rs.getInt("superbenutzer") == 0) { //wenn tinyint = 0 ist der boolean false
                        b.setSuperbenutzer(false);
                    } else {
                        b.setSuperbenutzer(true);//wenn tinyint = 1 ist der boolean true
                    }

                    return b;


                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;

    }
}

